using System;
using System.Collections.Generic;
using System.Collections;
using UnityEngine;

namespace EntityKit.Runtime
{
    public sealed class EntityComponentContainer
    {
        private IEntity mOwnerEntity;

        private Dictionary<System.Type, IEntityComponent> mComponents = null;

        public EntityComponentContainer(IEntity ownerEntity)
        {
            mComponents = new Dictionary<System.Type, IEntityComponent>();
            mOwnerEntity = ownerEntity;
        }


        public void CollectionComponents()
        {
            if (!(mOwnerEntity is Component entity))
                return;
            var components = entity.GetComponentsInChildren<IEntityComponent>(true);
            if (components == null)
                return;
            for (var i = 0; i < components.Length; i++)
            {
                AddEntityComponent(components[i]);
            }
        }

        public void AddEntityComponent(IEntityComponent component)
        {
            if (component != null)
            {
                if (mComponents.ContainsKey(component.GetType()))
                {
                    Debug.LogError($"Tried to add a duplicate component: {component.GetType()}");
                }
                else
                {
                    mComponents[component.GetType()] = component;
                    component.OnInit(mOwnerEntity);
                }
            }
            else
            {
                Debug.LogError($"Tried to add a null view for Element type [{mOwnerEntity.GetType()}].");
            }
        }

        public void RemoveEntityComponent(IEntityComponent component)
        {
            if (component != null)
            {
                if (!mComponents.Remove(component.GetType()))
                {
                    Debug.LogError($"Tried to remove a component that does not exist: {component.GetType()}");
                }
                else
                {
                    component.OnRelease();
                }
            }
            else
            {
                Debug.LogError("Tried to remove a null component.");
            }
        }

        public R GetEntityComponent<R>() where R : class, IEntityComponent
        {
            System.Type type = typeof(R);
            if (!mComponents.ContainsKey(type))
            {
                var error = $"{GetType()}: entity component {type} does not exist. Did you forget to add it by calling Add? Owner: {mOwnerEntity?.GetType()}";
                Debug.LogError(error);
                return null;
            }

            return mComponents[type] as R;
        }

        // 添加TryGet方法避免异常开销
        public bool TryGetEntityComponent<R>(out R component) where R : class, IEntityComponent
        {
            System.Type type = typeof(R);
            if (mComponents.TryGetValue(type, out IEntityComponent value))
            {
                component = value as R;
                return true;
            }

            component = null;
            return false;
        }

        public List<R> GetEntityComponents<R>() where R : class, IEntityComponent
        {
            List<R> result = new List<R>();
            foreach (var component in mComponents.Values)
            {
                if (component is R rComponent)
                {
                    result.Add(rComponent);
                }
            }

            return result;
        }

        public List<IEntityComponent> GetAllEntityComponents()
        {
            return new List<IEntityComponent>(mComponents.Values);
        }

        public bool Contains<R>() where R : IEntityComponent
        {
            System.Type type = typeof(R);
            return mComponents.ContainsKey(type);
        }

        public void OnInit(IEntity entity)
        {
            foreach (var component in mComponents.Values)
            {
                try
                {
                    if (component.IsInit)
                        throw new Exception("Component already initialized.");
                    component.OnInit(entity);
                }
                catch (System.Exception ex)
                {
                    Debug.LogError($"Error in OnInit for component {component.GetType()}: {ex.Message}\n{ex.StackTrace}");
                }
            }
        }

        public void OnUpdate()
        {
            foreach (var component in mComponents.Values)
            {
                try
                {
                    if (component.IsInit)
                        component.OnUpdate();
                }
                catch (System.Exception ex)
                {
                    Debug.LogError($"Error in OnUpdate for component {component.GetType()}: {ex.Message}\n{ex.StackTrace}");
                }
            }
        }

        public void OnRelease()
        {
            foreach (var component in mComponents.Values)
            {
                try
                {
                    // 更严格的空值检查
                    if (component == null || component.Equals(null))
                        continue;
                    if (!component.IsInit)
                        throw new Exception("不能释放未初始化的组件");
                    component.OnRelease();
                }
                catch (System.Exception ex)
                {
#if UNITY_EDITOR
                    Debug.LogWarning($"Expected error during editor shutdown for component {component?.GetType()}: {ex.Message}");
#else
                    Debug.LogError($"Error in OnRelease for component {component?.GetType()}: {ex.Message}\n{ex.StackTrace}");
#endif
                }
            }

            mComponents?.Clear();
        }
    }
}